---
title: "COVID-19"
output:
flexdashboard::flex_dashboard:
logo: rbmv_curve.png
orientation: rows
source_code: embed
theme: flatly
---
```{r setup, include=FALSE}
library(flexdashboard)
```
```{r, include=FALSE}
# Packages
library(tidyverse)
library(lubridate)
library(rvest)
library(sf)
library(leaflet)
library(plotly)
library(crosstalk)
library(rbmv)
library(classInt)
# imported functions
`%<>%` <- magrittr::`%<>%`
# custom functions
get_bins <- function(.data, bins = 8) {
#' use kmeans to automatically set sensible bins that represent the data well
#' requires 'classInt' package
#' @return a vector with 8 default bins
intervals <- classIntervals(.data, n = bins, style = "kmeans", rtimes = 5)
return(round(intervals$brks))
}
# API key
mapbox <- read_lines(".mapbox-key")
# Get the data + tidy
dph_covid19_page <- read_html("http://www.publichealth.lacounty.gov/media/Coronavirus/locations.htm")
dph_covid19_tbls <- dph_covid19_page %>%
html_nodes("table") %>%
html_table()
dph_covid19_messy <- dph_covid19_tbls[[1]] %>%
repair_names() %>%
janitor::clean_names() %>%
rename(locations = x1, total_cases = x2) %>%
select(-x3)
dph_covid19_totals <- dph_covid19_messy %>%
slice(2:11)
lac_total_cases <- parse_number(dph_covid19_totals$total_cases[[5]])
lac_total_deaths <- parse_number(dph_covid19_totals$total_cases[[10]])
dph_covid19_totals %>%
mutate(locations = str_remove_all(locations, "- ")) %>%
filter(locations %in% c("Long Beach", "Pasadena")) %>%
slice(1:2) %>%
mutate(locations = str_glue("City of {locations}") %>% parse_character(),
total_cases = parse_number(total_cases)) -> lb_pass
dph_covid19 <- dph_covid19_messy %>% slice(53:391) %>%
mutate(
locations = str_remove_all(locations, regex("\\*")),
total_cases = parse_number(total_cases, na = "--"),
locations = case_when(
str_detect(locations, "San Francisquito") ~ "Unincorporated - San Francisquito Canyon/Bouquet Canyon",
TRUE ~ locations)) %>%
filter(!locations == "Los Angeles") %>%
bind_rows(., lb_pass)
captions <- dph_covid19_page %>%
html_nodes("caption") %>%
html_text()
str_remove_all(captions[1], "\\r|\\n|\\t") %>%
str_split_fixed(., "\\*", 2) -> page_updated
# page_updated <- str_split_fixed(page_updated[1], " ", 4)[4]
# page_updated <- str_glue("{page_updated}/20")
# page_updated <- parse_date(page_updated, "%m/%d/%y")
# uncomment line below if the 'caption' html is up to date on the DPH website
# not sure if data is only updated the night before or not; in which case I will just update based
# on the day new data is available
page_updated <- today()
page_updated_string <- str_glue("{wday(page_updated, label = T)} {month(page_updated, label = T)} {day(page_updated)}, {year(page_updated)}")
gis <- st_read(
dsn = "data/gis/geo_export_871186bb-3266-4a1c-a0f6-8cda86b55d55.shp",
layer = "geo_export_871186bb-3266-4a1c-a0f6-8cda86b55d55",
quiet = T
)
gis %<>% st_transform(crs = 4326) %>%
mutate(label = as.character.factor(label))
lac_covid19 <- gis %>%
left_join(., dph_covid19, by = c("label" = "locations")) %>%
mutate(total_cases = if_else(is.na(total_cases), 0, total_cases))
covid19_cases <- read_csv("https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_US.csv")
covid19_deaths <- read_csv("https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_US.csv")
make_link <- function(date) {
date_format <- format(date, format = "%m-%d-%Y")
link <- str_glue("https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/{date_format}.csv")
return(link)
}
test_data <- function(date) {
link <- make_link(date)
status <- httr::http_status(httr::GET(link))
return(status$category)
}
get_world_data <- function(date) {
if (test_data(date) == "Success") {
return(make_link(date))
} else if (test_data(date) == "Client error") {
return(make_link(date - 1))
}
}
link <- get_world_data(today())
world <- read_csv(link)
world %<>% rename(long = Long_, lat = Lat)
covid19_time_series_cases <- covid19_cases %>%
filter(Admin2 == "Los Angeles") %>%
gather("date", "cases", 12:ncol(covid19_cases)) %>%
select(Admin2, date, cases) %>%
rename(county = Admin2) %>%
mutate(date = parse_date(date, "%m/%d/%y"),
case_type = "New Confirmed Case") %>%
bind_rows(
tribble(
~county, ~date, ~cases, ~case_type,
"Los Angeles", page_updated, lac_total_cases, "New Confirmed Case")) %>%
distinct()
covid19_time_series_deaths <- covid19_deaths %>%
filter(Admin2 == "Los Angeles") %>%
gather("date", "cases", 13:ncol(covid19_deaths)) %>%
select(Admin2, date, cases) %>%
rename(county = Admin2) %>%
mutate(date = parse_date(date, "%m/%d/%y"),
case_type = "Death") %>%
bind_rows(
tribble(
~county, ~date, ~cases, ~case_type,
"Los Angeles", page_updated, lac_total_deaths, "Death")) %>%
distinct()
covid19_time_series <- bind_rows(covid19_time_series_cases, covid19_time_series_deaths)
covid19_cases %<>% mutate(Combined_Key = str_remove(Combined_Key, ", US"))
covid19_cases_top10_us <- covid19_cases %>%
arrange(desc(.[[ncol(covid19_cases)]])) %>%
slice(1:10) %>%
gather("date", "cases", 12:ncol(covid19_cases)) %>%
select(Combined_Key, date, cases) %>%
rename(location = Combined_Key) %>%
mutate(
location = str_remove(location, ", US"),
date = parse_date(date, "%m/%d/%y"),
case_type = "New Confirmed Case") %>%
distinct()
covid19_state_cases <- covid19_cases %>%
filter(iso3 == "USA") %>%
gather("date", "cases", 12:ncol(covid19_cases)) %>%
rename(state = Province_State) %>%
group_by(state, date) %>%
summarise(cases = sum(cases)) %>%
mutate(date = parse_date(date, "%m/%d/%y"))
light_blue <- rbmv_pal("main", plotly = T)[1]
ruby <- rbmv_pal("main", plotly = T)[2]
pale_black <- rbmv_pal("main", plotly = T)[5]
sd <- SharedData$new(covid19_cases_top10_us, ~location, "Select a city")
```
LA County {data-icon="fa-map"}
=====================================
Row {data-height=510}
-------------------------------------
###
```{r}
bins <- get_bins(lac_covid19$total_cases, bins = 12)
pal <- colorBin(
palette = rbmv_pal("spectrum", plotly = T),
domain = lac_covid19$total_cases,
bins = bins)
label <- str_glue("{lac_covid19$label}
Total cases: {lac_covid19$total_cases}") %>%
lapply(htmltools::HTML)
lac_covid19 %>%
leaflet() %>%
addTiles(mapbox, attribution = paste("Data from Los Angeles County Department of Public Health COVID-19 location table")) %>%
addPolygons(
fillColor = ~pal(total_cases),
weight = 1.5,
fillOpacity = 0.7,
smoothFactor = 0.5,
color = "white",
label = label,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto")) %>%
addLegend(
pal = pal, values = ~total_cases, opacity = 0.7,
title = NULL, position = "bottomright") %>%
setView(-118.2, 34, zoom = 9.5)
```
Row {data-height=400}
-------------------------------------
###
```{r}
source <- list(
x = 1, y = -0.25, text = "Source: 2019 Novel Coronavirus COVID-19 (2019-nCoV)\nData Repository by Johns Hopkins CSSE",
showarrow = F, xref = "paper", yref = "paper", xanchor = "right", yanchor = "auto",
xshif = 0, yshift = 0, font = list(size = 12, color = "grey")
)
base <- plot_ly(sd, color = I(rbmv_pal(plotly = T)[6]), height = 320) %>%
group_by(location)
left_bar <- base %>%
add_bars(x = ~cases, y = ~location, hoverinfo = "text",
text = ~paste("Click bar to highlight line
on the left")) %>%
layout(
barmode = "overlay",
xaxis = list(title = ""),
yaxis = list(
title = "",
categoryorder = "max ascending")
)
right_line <- base %>%
add_lines(x = ~date, y = ~cases, alpha = 0.3, hoverinfo = "text",
text = ~paste(" Location: ", location,
" Case type: ", case_type, "x Log Scale",
" Cases: ", scales::comma(cases))) %>%
layout(xaxis = list(title = ""),
yaxis = list(type = "log"))
subplot(left_bar, right_line, titleX = TRUE, widths = c(.3, .7)) %>%
layout(title = "How does Los Angeles County compare to other major outbreak centers",
margin = list(l = 120, b = 40), annotations = source) %>%
hide_legend() %>%
highlight("plotly_click", color = rbmv_pal(plotly = T)[2]) %>%
config(displayModeBar = FALSE)
```
Row {data-height=110}
-------------------------------------
###
```{r}
valueBox(page_updated_string, color = light_blue, icon = "fa-calendar", caption = "Data pulled from both LAC DPH and John Hopkins CSSE")
```
###
```{r}
total_cases <- scales::comma(last(covid19_time_series_cases$cases))
valueBox(total_cases, color = ruby, icon = "fa-ambulance", caption = "Total Lab Confirmed COVID-19 Cases in LAC")
```
###
```{r}
total_deaths <- scales::comma(last(covid19_time_series_deaths$cases))
valueBox(total_deaths, color = pale_black, icon = "fa-medkit", caption = "Total COVID-19 Related Deaths")
```
US States {data-icon="fa-chart-line"}
=====================================
###
```{r}
bins <- get_bins(covid19_state_cases$cases, bins = 9)
colors <- rbmv_pal("spectrum", plotly = TRUE)
normalize <- function(x) round((x-min(x))/(max(x)-min(x)), 4)
state_colors <- tibble(range = bins, hex = colors) %>%
mutate(range = normalize(range))
plot_ly(covid19_state_cases) %>%
add_heatmap(x = ~date, y = ~state, z = ~cases,
colorscale = state_colors,
showscale = F, opacity = .85,
text = ~paste(
"Date: ", date, "
State: ", state,
"
Total confirmed cases: ", scales::comma(cases)),
hoverinfo = "text") %>%
layout(
title = "COVID19 Cases",
xaxis = list(title = "Date"),
yaxis = list(title = "", autorange = "reversed")) %>%
config(displayModeBar = FALSE)
```
Global {data-icon="fa-globe"}
=====================================
###
```{r}
bins <- get_bins(world$Confirmed, bins = 12)
pal <- colorBin(
palette = rbmv_pal("warm", plotly = T),
domain = world$Confirmed,
bins = bins)
label <- str_glue("Location: {world$Combined_Key}
Cases: {scales::comma(world$Confirmed)}
Deaths: {scales::comma(world$Deaths)}
Active: {scales::comma(world$Active)}
Recovered: {scales::comma(world$Recovered)}
Last Update: {world$Last_Update}") %>%
lapply(htmltools::HTML)
world %>%
leaflet() %>%
addTiles(mapbox, attribution = paste("Data from Novel Coronavirus (COVID-19) Cases, provided by JHU CSSE")) %>%
addCircleMarkers(
lng = ~long, lat = ~lat,
label = ~label,
color = ~pal(Confirmed),
radius = ~ifelse(Confirmed >= 30000, 25, 15),
stroke = FALSE, fillOpacity = .7,
clusterOptions = markerClusterOptions(
showCoverageOnHover = FALSE),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto")) %>%
addLegend(title = "COVID-19 Cases", opacity = 0.6, pal = pal, values = ~Confirmed, position = "bottomright")
```